<?php
/**
 * Created by PhpStorm.
 * User: jaylen
 * Date: 2020-05-14
 * Time: 19:36
 */

namespace app\admin\model;


use app\common\model\BaseModel;
use app\common\service\Redis;
use think\facade\Config;
use think\model\concern\SoftDelete;

class SystemLog extends BaseModel
{
    protected $hidden = ['update_time','delete_time'];
    protected $redis = null;
    protected const LOG_KEY = "tn_vue_bof_system_log_key";
    protected const USE_REDIS = true;   // 是否使用redis进行缓存Log

    // 使用软删除
    use SoftDelete;
    protected $deleteTime = 'delete_time';

    public function __construct(array $data = [])
    {
        parent::__construct($data);

        if (static::USE_REDIS) {
            // 取出redis配置信息
            $redisConfig = Config::get('redis');
            $this->redis = new Redis($redisConfig);
        }

    }

    /**
     * 获取系统日志的分页数据
     * @param array $params
     * @return \think\Paginator
     */
    public static function getPaginationList(array $params)
    {
        static::validatePaginationData($params);

        $static = new static();

        // 同步redis中的日志数据
        $static->asyncSystemLogToDataBase();

        $static = $static->order('create_time','desc');

        foreach ($params as $name => $value) {
            $value = !is_array($value) ? trim($value) : $value;
            switch ($name) {
                case 'user_name':
                    if (!empty($value)) {
                        $like_text = '%' . $value . '%';
                        $static = $static->whereLike('user_name', $like_text);
                    }
                    break;
                case 'controller':
                    if (!empty($value)) {
                        $like_text = '%' . $value . '%';
                        $static = $static->whereLike('controller', $like_text);
                    }
                    break;
                case 'method':
                    if (!empty($value)) {
                        $like_text = '%' . $value . '%';
                        $static = $static->whereLike('method', $like_text);
                    }
                    break;
                case 'date_range':
                    if (!empty($value)) {
                        $static = $static->whereBetweenTime('create_time', $value[0], $value[1]);
                    }
                    break;
                case 'sort_order':
                    if (!empty($value)) {
                        $static = $static->order($params['sort_prop'], $value == 'descending' ? 'desc' : 'asc');
                    }
                    break;
            }
        }

        return $static
            ->paginate([
                'page' => $params['page'],
                'list_rows' => $params['limit']
            ], false);
    }

    /**
     * 删除所有的Log日志
     * @return bool
     */
    public static function clearAllLog()
    {
        $result = static::destroy(function ($query){
            $query->whereRaw('1=1');
        });

        if ($result !== false) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * 将日志写入到Redis中
     * @param string $content
     * @param string $user_name
     * @param string $controller
     * @param string $action
     */
    public function writeSystemLog(string $content, string $user_name = '', string $controller = '', string $action = '')
    {
        // 如果关闭了日志记录则不进行记录
        if (get_system_config('bk_log_on') === '关闭') {
            return ;
        }

        if (empty($user_name)) {
            $current_user = Admin::getCurrentUser();
            $user_name = $current_user['user_name'];
        }
        // 组合需要添加的数据
        $logData = [
            'user_name' => !empty($user_name) ? $user_name : '',
            'controller' => $controller,
            'method' => $action,
            'content' => $content,
            'ip_address' => PHP_SAPI === 'cli' ? '127.0.0.1' : request()->ip(),
            'create_time' => time(),
        ];

        // 将日志写到Redis中
        if (static::USE_REDIS) {
            $this->redis->rPush(static::LOG_KEY,json_encode($logData,JSON_UNESCAPED_UNICODE));  // 使用List列表进行存储，保证最新的在最后（插入到尾部）
        } else {
            static::allowField(['user_name','controller','method','content','ip_address','create_time'])
                ->save($logData);
        }

    }

    /**
     * 同步日志到数据库中
     * @return bool|void
     * @throws \Exception
     */
    public function asyncSystemLogToDataBase()
    {

        if (!static::USE_REDIS) {
            return true;
        }

        // 从Redis中取出日志，并删除Redis记录
        $redisLog = $this->redis->getListData(static::LOG_KEY);
        if (empty($redisLog)) {
            return true;
        }

        $LogData = [];
        foreach ($redisLog as $value) {
            $LogData[] = json_decode($value,true);
        }

        // 将数据写入到数数据库中
        $systemLog = new static();
        $result = $systemLog->allowField(['user_name','controller','method','content','ip_address','create_time'])
            ->saveAll($LogData);

        if ($result !== false) {
            $this->redis->clear(static::LOG_KEY);
        }

//        // 对数组进行排序
//        $create_time = array_column($LogData,'create_time');
//        array_multisort($create_time,SORT_ASC,$LogData);

        return true;
    }
}